// rp ++ never say die
#include <bits/stdc++.h>
using namespace std;

const int N = 3300, INF = 2e6;

int t, n, m, l, v, p[N];
struct node {
	int d, v, a;
} a[N];
struct pr{
	double l, r;
	friend bool operator < (const struct pr A, const struct pr B)
	{
		if (A.r != B.r)
			return A.r < B.r;
		return A.l > B.l;
	}
} range[N];

void init()
{
	for (int i = 1; i <= n; i ++ )
	{
		int D = a[i].d, V = a[i].v, A = a[i].a;
		if (V > v && A > 0)
			range[i] = {D*1.0, INF};

		if (V <= v && A > 0)
			range[i] = {D*1.0 + 1.0*(v*v-V*V)/(2*A), INF};

		if (V >= v && A < 0)
			range[i] = {D*1.0, 1.0*D + 1.0*(v*v-V*V)/(2*A)};

		if (V < v && A < 0)
			range[i] = {-1.0, -1.0};

		if (A == 0)
		{
			if (V > v)
				range[i] = {D*1.0, INF};
			else range[i] = {-1, -1};
		}
	}
}
int task1ans = 0, task2ans = 0;
vector<pr> rng;
void task1()
{
	for (int i = 1; i <= n; i ++ )
	{
		bool flag = false;
		for (int j = 1; j <= m; j ++ )
			if (range[i].l <= p[j] && p[j] <= range[i].r)
			{
				rng.push_back(range[i]);
				flag = true;
				break;
			}
		task1ans += flag;
	}
}
pr px[N], px2[N];
bool cmp(pr a, pr b)
{
	if (a.l != b.l)
		return a.l < b.l;
	return a.r > b.r;
}
bool vis[N], use[N];

void task2()
{
	if (rng.size() == 0)
	{
		task2ans = m;
		return;
	}
	vector<pr> tmp;
	for (int i = 1; i <= m; i ++ )
	{
		int top = -1;
		for (int j = 0; j < rng.size(); j ++ )
		{
			if (rng[j].l <= p[i] && p[i] <= rng[j].r)
			{
				if (top == -1) top = j + 1;
				if (j == rng.size() - 1)
					px[i] = {top*1.0, j*1.0 + 1.0};
			} else if (top != -1)
			{
				px[i] = {top*1.0, j*1.0};
				break;
			}
		}
	}
	for (int i = 1; i <= m; i ++ )
	for (int j = 1; j <= m; j ++ )
	{
		if (i == j) continue;
		if (vis[j]) continue;
		if (px[i].l == 0 && px[i].r == 0) vis[i] = true;
		if (px[j].l <= px[i].l && px[i].r <= px[j].r)
		{
			vis[i] = true;
			break;
		}
	}
	for (int i = 1; i <= m; i ++ )
		if (!vis[i]) tmp.push_back(px[i]);
	if (tmp.size() <= 2)
	{
		task2ans = m - tmp.size();
		return;
	}
	int ll = 1, rr = tmp.size() - 2;
	int llmax = tmp[0].r, rrmax = tmp[tmp.size() - 1].l;
	sort(tmp.begin(), tmp.end());
	use[0] = true, use[tmp.size() - 1] = true;
	while (llmax + 1 < rrmax && ll <= rr && ll < tmp.size() &&  0 <= rr)
	{
		if (tmp[ll].l - 1 >= llmax) llmax = tmp[ll].r, use[ll] = true;
		if (tmp[rr].r + 1 >= rrmax) rrmax = tmp[rr].l, use[rr] = true;
		ll ++, rr --;
	}
	for (int i = 0; i <= m - 1; i ++ )
			if (use[i]) task2ans ++;
	task2ans = m - task2ans;

}

void koishi()
{
	scanf("%d", &t);
	while (t -- )
	{
		cin >> n >> m >> l >> v;
		for (int i = 1; i <= n; i ++ )
			scanf("%d%d%d",&a[i].d, &a[i].v, &a[i].a);
		for (int i = 1; i <= m; i ++ )
			scanf("%d",p + i);
		init();
		sort (range + 1, range + 1 + n);
		sort (p + 1, p + 1 + m);
		task1();
		sort(rng.begin(),rng.end());
		task2();
		printf("%d %d\n",task1ans,task2ans);
		task1ans = 0;
		task2ans = 0;
		for (int i = 1; i <= m; i ++ )
			px[i] = {0,0};
		rng.clear();
		memset(vis, 0, sizeof vis);
		memset(use, 0, sizeof use);
	}
}


int main()
{
	freopen("detect.in","r",stdin);
	freopen("detect.out","w",stdout);
	koishi();
	return 0;
}
